// echo aux function only, should not compile alone.
// -r:"../../Backend/System.IO.FileSystem.dll"

//! 编译方法，目前来说只能是自己改上面那行字，把缺的东西都补齐，之后送命令提示符或者用python脚本编译。
//! windows就是一坨shit……连通配符都不支持……不然我至少能写出类似 dotnet C:\Program Files\dotnet\sdk\*\Roslyn\bincore\csc.dll 这样的语法

// -r:"../../The Scroll of Taiwu_Data/Managed/Mono.Cecil.dll" -r:"../../The Scroll of Taiwu_Data/Managed/System.Core.dll"   -r:"../../The Scroll of Taiwu_Data/Managed/System.Composition.AttributedModel.dll" -r:"../../Backend/System.Runtime.dll"
/**
 *  Everyone's Unity Game Plugin
 *  Copyright (C) 2022 Neutron3529
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as
 *  published by the Free Software Foundation, either version 3 of the
 *  License, or (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */
//! 这是一个自带文档注释的Mod，虽然代码很shit，但里面有不少注释，或许会对之后准备玩过月逻辑的人有帮助。
//! 所有文档注释会用//!开头，请注意搜索
//! 首先是前后端，前端对后端的调用会先被塞进 ProcessMethodCall，之后分发给对应domain的CallMethod，由CallMethod进行进一步的分发。借助这一点，我们可以快速找到前端调用究竟是在使用哪个函数。
using System;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Collections.Generic;
using static Utils.Logger;
using static Utils.Event;

using Config.EventConfig;
using GameData.Domains.TaiwuEvent;
using GameData.Domains.TaiwuEvent.Enum;

namespace Neutron3529.ChaosEvents {
    public partial class ChaosEvents : EventPackage {
        public 公用.公用 ECMN(){
            var o=new 公用.公用();
            {
                var taiwuEvent = GameData.Domains.DomainManager.TaiwuEvent.GetEvent("fb38f657-6ed0-41e4-a0c2-c82afb49762f"); // @人物互动-恩义互动
                var lst=taiwuEvent.EventConfig.EventOptions.ToList();
                for(int i=0;i<o.EventOptions.Length;i++){
                    lst.Insert(lst.Count-1, o.EventOptions[i]);
                }
                taiwuEvent.EventConfig.EventOptions=lst.ToArray();
            }
            return o;
        }
    }
    namespace 公用 {
        public class 公用 : EventContainer {
            public static FieldInfo _gender = typeof(GameData.Domains.Character.Character).GetField("_gender",(BindingFlags)(-1)); // sbyte
            public static uint Gender_Offset = (uint)(typeof(GameData.Domains.Character.Character).GetNestedType("FixedFieldInfos",(BindingFlags)(-1)).GetField("Gender_Offset").GetValue(null));
            public static int Gender_Size = (int)(typeof(GameData.Domains.Character.Character).GetNestedType("FixedFieldInfos",(BindingFlags)(-1)).GetField("Gender_Size").GetValue(null));
            public static FieldInfo _transgender = typeof(GameData.Domains.Character.Character).GetField("_transgender",(BindingFlags)(-1)); // bool
            public static uint Transgender_Offset = (uint)(typeof(GameData.Domains.Character.Character).GetNestedType("FixedFieldInfos",(BindingFlags)(-1)).GetField("Transgender_Offset").GetValue(null));
            public static int Transgender_Size = (int)(typeof(GameData.Domains.Character.Character).GetNestedType("FixedFieldInfos",(BindingFlags)(-1)).GetField("Transgender_Size").GetValue(null));
            public static FieldInfo _bisexual = typeof(GameData.Domains.Character.Character).GetField("_bisexual",(BindingFlags)(-1)); // bool
            public static uint Bisexual_Offset = (uint)(typeof(GameData.Domains.Character.Character).GetNestedType("FixedFieldInfos",(BindingFlags)(-1)).GetField("Bisexual_Offset").GetValue(null));
            public static int Bisexual_Size = (int)(typeof(GameData.Domains.Character.Character).GetNestedType("FixedFieldInfos",(BindingFlags)(-1)).GetField("Bisexual_Size").GetValue(null));
            unsafe static void SetGender(GameData.Domains.Character.Character character, sbyte value){
                _gender.SetValue(character,value);
                *(sbyte*)GameData.ArchiveData.OperationAdder.DynamicObjectCollection_SetFixedField<int>(character.CollectionHelperData.DomainId, character.CollectionHelperData.DataId, character.GetId(), Gender_Offset, Gender_Size)=value;
            }
            unsafe static void SetTransgender(GameData.Domains.Character.Character character, bool value){
                _transgender.SetValue(character,value);
                *(bool*)GameData.ArchiveData.OperationAdder.DynamicObjectCollection_SetFixedField<int>(character.CollectionHelperData.DomainId, character.CollectionHelperData.DataId, character.GetId(), Transgender_Offset, Transgender_Size)=value;
            }
            unsafe static void SetBisexual(GameData.Domains.Character.Character character, bool value){
                _bisexual.SetValue(character,value);
                *(bool*)GameData.ArchiveData.OperationAdder.DynamicObjectCollection_SetFixedField<int>(character.CollectionHelperData.DomainId, character.CollectionHelperData.DataId, character.GetId(), Bisexual_Offset, Bisexual_Size)=value;
            }
            public 公用() :base("Prof.公用", "70b4d45d-ba15-423d-b94e-b40e348eb9be"){
                this.EventOptions = new TaiwuEventOption[1];//你待在此地，不要走动
                for(int i=0;i<this.EventOptions.Length;i++){
                    var op=new TaiwuEventOption {
                        OptionKey = "Option_3529009"+(i+1).ToString("01"),
                        OnOptionSelect = new Func<string>(this.OnOptionSelect(i)),
                        OnOptionVisibleCheck = new Func<bool>(this.OnCheckOptionCondition(i)),
                        OnOptionAvailableCheck = new Func<bool>(this.OnCheckEventCondition),
                        GetReplacedContent = new Func<string>(this.Desc(i)),
                        GetExtraFormatLanguageKeys = new Func<List<string>>(this.GetExtraFormatLanguageKeys)
                    };
                    this.EventOptions[i]=op;
                }
                {
                    var taiwuEvent = GameData.Domains.DomainManager.TaiwuEvent.GetEvent("5b468c96-6a8b-4c19-97c2-990ab61a5cd8"); // 门派较武-转点a-空桑-1-1
                    var lst=taiwuEvent.EventConfig.EventOptions;
                    for(int i=0;i<lst.Length;i++){
                        if(lst[i].OptionKey == "Option_-1821452429"){ // （选择<Item key=TrueMedicine str=Name/>……）
                            var opt=lst[i];
                            lst[i].SetContent("（选择"+Grade("<Item key=TrueMedicine str=Name/>",0)+"……）");
                            break;
                        }
                    }
                }
                {
                    var taiwuEvent = GameData.Domains.DomainManager.TaiwuEvent.GetEvent("bad63f08-115a-45aa-970c-fa203dd85e2b"); // @人物互动-亲近互动
                    var lst=taiwuEvent.EventConfig.EventOptions;
                    for(int i=0;i<lst.Length;i++){
                        if(lst[i].OptionKey == "Option_-402489472"){ // 男媒女妁
                            var opt=lst[i];
                            opt.OnOptionVisibleCheck=enable("N09-Add")?()=>GameData.Domains.TaiwuEvent.EventHelper.EventHelper.CheckMainStoryLineProgress(8):()=>GameData.Domains.TaiwuEvent.EventHelper.EventHelper.CheckMainStoryLineProgress(8) && GameData.Domains.TaiwuEvent.EventHelper.EventHelper.GetRoleAge(opt.ArgBox.GetCharacter("CharacterId")) > 15;break;
                        }
                    }
                }
                {
                    var taiwuEvent = GameData.Domains.DomainManager.TaiwuEvent.GetEvent("b8005870-7a8e-43d2-a00c-4273b4ccacfb"); // 生育-正常得子-母亲得子-2
                    var lst=taiwuEvent.EventConfig.EventOptions.ToList();
                    for(int i=0;i<lst.Count;i++){
                        if(lst[i].OptionKey == "Option_-137861619"){
                            var opt=lst[i];
                            lst[i].GetReplacedContent=()=>{
                                try{
                                    return "（决定了，孩子就叫"+Name(opt.ArgBox.GetCharacter("MonthlyEvent_arg2"))+"……）";
                                } catch(Exception e){
                                    logex(e);
                                }
                                return string.Empty;
                            };
                            break;
                        }
                    }
                    for(int i=0;i<3;i++){
                        if((i==0 && Gender_Size!=1) || (i==1 && Transgender_Size!=1) || (i==2 && Bisexual_Size!=1)) continue;
                        var opt=new TaiwuEventOption {
                            OptionKey = "Option_3529009"+(i+3).ToString("01")
                        };
                        opt.OnOptionSelect = i==0?this.mGender(opt):i==1?this.mTrans(opt):this.mBisex(opt);
                        opt.OnOptionVisibleCheck = new Func<bool>(()=>opt.ArgBox.GetCharacter("MonthlyEvent_arg2")!=null);
                        opt.OnOptionAvailableCheck = new Func<bool>(()=>opt.ArgBox.GetCharacter("MonthlyEvent_arg2")!=null);
                        opt.GetReplacedContent = i==0?this.dGender(opt):i==1?this.dTrans(opt):this.dBisex(opt);
                        opt.GetExtraFormatLanguageKeys = new Func<List<string>>(this.GetExtraFormatLanguageKeys);
                        lst.Insert(lst.Count-1,opt);
                    }
                    taiwuEvent.EventConfig.EventOptions=lst.ToArray();
                }
            }
            private Func<string> mGender(TaiwuEventOption opt)=>()=>{
                var x=opt.ArgBox.GetCharacter("MonthlyEvent_arg2");
                SetGender(x,(sbyte)(1-x.GetGender()));
                SetTransgender(x,!x.GetTransgender());
                x.SetFullName(GameData.Domains.Character.CharacterDomain.GenerateRandomHanName(this.context.Random, x.GetFullName().GetCustomSurnameId(), x.GetFullName().GetSurnameId(), x.GetGender(), -1),this.context);
                return "b8005870-7a8e-43d2-a00c-4273b4ccacfb";
            };
            private Func<string> mTrans(TaiwuEventOption opt)=>()=>{
                var x=opt.ArgBox.GetCharacter("MonthlyEvent_arg2");
                x.GetAvatar().AvatarId=(byte)(((x.GetAvatar().AvatarId-1)^1)+1);
                x.SetAvatar(x.GetAvatar(),this.context);
                SetTransgender(x,!x.GetTransgender());
                return "b8005870-7a8e-43d2-a00c-4273b4ccacfb";
            };
            private Func<string> mBisex(TaiwuEventOption opt)=>()=>{
                var x=opt.ArgBox.GetCharacter("MonthlyEvent_arg2");
                SetBisexual(x,!x.GetBisexual());
                return "b8005870-7a8e-43d2-a00c-4273b4ccacfb";
            };
            private Func<string> dGender(TaiwuEventOption opt)=>()=>{
                var x=opt.ArgBox.GetCharacter("MonthlyEvent_arg2");
                return "（虽然大家都说这是"+Grade(x.GetGender()==0?"可爱的女孩子":"活泼的男孩子",0)+"，但我越看越觉得……）";
            };
            private Func<string> dTrans(TaiwuEventOption opt)=>()=>{
                var x=opt.ArgBox.GetCharacter("MonthlyEvent_arg2");
                return "（虽然大家都觉得这个"+(x.GetGender()==0?"女孩子":"男孩子")+"长得"+Grade((x.GetTransgender()^(x.GetGender()==0))?"柔美":"阳刚",0)+"但……）";
            };
            private Func<string> dBisex(TaiwuEventOption opt)=>()=>{
                var x=opt.ArgBox.GetCharacter("MonthlyEvent_arg2");
                return "（虽然大家都说这孩子长大之后一定"+Grade(x.GetBisexual()?"招"+(x.GetGender()==0?"女":"男")+"孩子喜欢":"能找到"+(x.GetGender()==0?"帅气老公":"漂亮老婆"),0)+"，但……）";
            };
            private Func<bool> OnCheckOptionCondition(int index){
                switch(index){
                    case 0: return ()=>{
                        var taiwuChar=this.EventOptions[index].ArgBox.GetCharacter("RoleTaiwu");
                        if(taiwuChar==null)return false;
                        var location = taiwuChar.GetLocation();
                        if (!location.IsValid()){
                            return false;
                        }
                        var character=this.EventOptions[index].ArgBox.GetCharacter("CharacterId");
                        return character!=null && GameData.Domains.TaiwuEvent.EventHelper.EventHelper.IsInGroup(character.GetId());
                    };
                    default: return ()=>false;
                }
            }
            private unsafe Func<string> OnOptionSelect(int index){
                switch(index){
                    case 0:return ()=>{
                        var character=this.EventOptions[index].ArgBox.GetCharacter("CharacterId");
                        GameData.Domains.DomainManager.Taiwu.LeaveGroup(context, character.GetId(),true, true, false);
                        return Goto("“我就吃两个，剩下的都给你”\n<Character key=CharacterId str=Name/>答应得很是爽朗。","（哭笑不得……）",index); // @人物互动-恩义互动
                    };
                    default: return ()=>string.Empty;
                }
            }
            public override Func<string> Desc(int index){
                switch(index){
                    case 0:
                        return ()=>"（我买几个橘子去。你就在此地，不要走动……）";
                    default: return ()=>string.Empty;
                }
            }
        }
    }
}
